--[[
Copyright (C) 2006  Matt Richard

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
]]

-- Convenience functions for building the GUI
local function createTexture(parent, layer, w, h, f, ...)
    local t = parent:CreateTexture(nil, layer)
    t:SetWidth(w)
    t:SetHeight(h)
    t:SetTexture(f)
    if select("#",...) > 0 then t:SetPoint(...) end
    return t
end

local function createSlicedTexture(name, parent, width, middleHeight, file, ...)
    local top = createTexture(parent, "BACKGROUND", width, 30, file, ...)
    top:SetTexCoord(0, 1, 0, 30/256)
    parent[name .. "_top"] = top
    
    local middle = createTexture(parent, "BACKGROUND", width, middleHeight, file, "TOP", top, "BOTTOM")
    middle:SetTexCoord(0, 1, 30/256, 55/256)
    parent[name .. "_middle"] = middle
    
    local bottom = createTexture(parent, "BACKGROUND", width, 201, file, "TOP", middle, "BOTTOM")
    bottom:SetTexCoord(0, 1, 55/256, 1)
    parent[name .. "_bottom"] = bottom
end

local function createScrollButtonTexture(...)
    local t = createTexture(...)
    t:SetTexCoord(0.25, 0.75, 0.25, 0.75)
    return t
end

local function createScrollButton(parent, texName, dir, point, x, y)
    local b = CreateFrame("Button", nil, parent)
    local n = "Interface/Buttons/UI-ScrollBar-Scroll" .. texName
    b:SetWidth(16)
    b:SetHeight(16)
    
    local relPoint = point == "TOP" and "BOTTOM" or "TOP"
    b:SetPoint(point, parent, relPoint, x, y)
    
    b:SetNormalTexture(createScrollButtonTexture(b, "ARTWORK", 16, 16, n.."-Up", "CENTER"))
    b:SetPushedTexture(createScrollButtonTexture(b, "ARTWORK", 16, 16, n.."-Down", "CENTER"))
    b:SetDisabledTexture(createScrollButtonTexture(b, "ARTWORK", 16, 16, n.."-Disabled", "CENTER"))
    local t = createScrollButtonTexture(b, "HIGHLIGHT", 16, 16, n.."-Highlight", "CENTER")
    t:SetBlendMode("ADD")
    b:SetHighlightTexture(t)
    
    b:SetScript("OnClick",function(self)
        Overlord:OnMouseWheel(dir)
        PlaySound("UChatScrollButton")
    end)
    
    return b
end

local function createStandardButton(parent,x,y,text,onClick,...)
    local b = CreateFrame("Button",nil,parent,"UIPanelButtonTemplate")
    b:SetWidth(x)
    b:SetHeight(y)
    b:SetText(text)
    b:SetScript("OnClick",function() Overlord[onClick](Overlord) end)
    b:SetPoint(...)
    return b
end


function Overlord:CreateGUI()
    if self.frame then return end
    -- Create the frame and set basic attributes
    local f = CreateFrame("Frame","OverlordAddonsFrame",UIParent)
    table.insert(UISpecialFrames, "OverlordAddonsFrame")
    
    f:Hide()
    self.frame = f
    local stretch = 20
    f:SetWidth(640)
    f:SetHeight(512 + stretch)
    f:SetPoint("CENTER")
    f:CreateTitleRegion():SetAllPoints(f)
    f:SetHitRectInsets(0,44,0,13)
    f:EnableMouse(true)
    f:SetToplevel(true)
    f:SetFrameStrata("DIALOG")
    f:SetScript("OnShow",function(self) Overlord:OnShow() end)
    f:SetScript("OnHide",function() Overlord:HideGUI() end)
    
    -- Backdrop    
    local n = "Interface\\HelpFrame\\HelpFrame-"
    local middleHeight = stretch + 25
    createSlicedTexture("topleft", f, 256, middleHeight, n .. "TopLeft", "TOPLEFT")
    createSlicedTexture("top", f, 256, middleHeight, n .. "Top", "TOPLEFT", 256, 0)
    createSlicedTexture("topright", f, 128, middleHeight, n .. "TopRight", "TOPRIGHT")

    f.bottomleft = createTexture(f, "BACKGROUND", 256, 256, n.."BotLeft", "BOTTOMLEFT")
    f.bottom = createTexture(f, "BACKGROUND", 256, 256, n.."Bottom", "BOTTOMLEFT", 256, 0)
    f.bottomright = createTexture(f, "BACKGROUND", 128, 256, n.."BotRight", "BOTTOMRIGHT")
    
    -- Header
    f.header = createTexture(f, "BORDER", 256, 64, "Interface\\DialogFrame\\UI-DialogBox-Header", "TOP", -22, 12)
    local t = f:CreateFontString(nil,nil,"GameFontNormal") t:SetPoint("TOP", f.header, 0, -14) t:SetText("Overlord")    
    
    -- CloseButton
    CreateFrame("Button",nil,f,"UIPanelCloseButton"):SetPoint("TOPRIGHT",-42,-3)
    
    local numAddOns = GetNumAddOns()
    -- Scroll Bar
    local bar = CreateFrame("Slider",nil,f)
    f.bar = bar
    bar:SetOrientation("VERTICAL")
    bar:SetWidth(30)
    bar:SetHeight(379)
    bar:SetPoint("TOPRIGHT",-52,-68 - stretch)
    bar:SetMinMaxValues(0,(numAddOns - 22) > 0 and numAddOns - 22 or 0)
    bar:SetValueStep(1)
    bar:SetScript("OnValueChanged",function(self,value) Overlord:ScrollbarOnValueChanged(self, value) end)
    
    n = "Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar"
    bar.top = createTexture(bar, "BACKGROUND", 31, 256, n, "TOP", 0, 18)
    bar.top:SetTexCoord(0, 0.484375, 0, 1)
    
    bar.bottom = createTexture(bar, "BACKGROUND", 31, 106, n, "BOTTOM", 0, -20)
    bar.bottom:SetTexCoord(0.515625, 1, 0, 0.4140625)
    
    bar.middle = createTexture(bar, "BACKGROUND", 31, 60, n, "TOP", bar.top, "BOTTOM")
    bar.middle:SetPoint("BOTTOM", bar.bottom, "TOP")
    bar.middle:SetTexCoord(0, 0.484375, 1, .75)
    
    -- Scroll Up/Down buttons
    bar.upButton = createScrollButton(bar, "UpButton", 1, "BOTTOM", 0, -2)
    bar.downButton = createScrollButton(bar, "DownButton", -1, "TOP", 0, -2)
    
    -- Thumb Button
    local t = createTexture(bar, nil, 16, 16, "Interface/Buttons/UI-ScrollBar-Knob")
    t:SetTexCoord(0.25, 0.75, 0.75, 0.25)
    bar:SetThumbTexture(t)
    
    -- Mousewheel catcher frame
    do
        local f = CreateFrame("Frame",nil,f)
        f:SetPoint("TOPLEFT", 21, -57)
        f:SetWidth(535)
        f:SetHeight(396)
        f:EnableMouseWheel(true)
        f:SetScript("OnMouseWheel",function(self, delta) Overlord:OnMouseWheel(delta) end)
    end
        
    -- Selection Buttons
    local t = f:CreateFontString(nil,nil,"GameFontNormal") t:SetPoint("TOPLEFT", 250, -3 - stretch) t:SetWidth(80*4) t:SetText("Quick Select")
    f.selectAll = createStandardButton(f, 80, 24, ALL, "SelectAll", "TOPLEFT", 250, -18 - stretch)
    f.selectNone = createStandardButton(f, 80, 24, NONE, "ClearSelection", "LEFT", f.selectAll, "RIGHT")
    f.selectEnabled = createStandardButton(f, 80, 24, "Enabled", "SelectEnabled", "LEFT", f.selectNone, "RIGHT")
    f.selectAll = createStandardButton(f, 80, 24, ADDON_DISABLED, "SelectDisabled", "LEFT", f.selectEnabled, "RIGHT")
    
    -- Enable / Disable Buttons
    f.enableSelected = createStandardButton(f, 140, 20, "Enable Selected", "EnableSelected", "BOTTOMLEFT", 21, 22)
    f.disableSelected = createStandardButton(f, 140, 20, "Disable Selected", "DisableSelected", "LEFT", f.enableSelected, "RIGHT", 5, 0)
    
    -- Okay / ReloadUI buttons
    f.okay = createStandardButton(f, 90, 20, OKAY, "HideGUI", "BOTTOMRIGHT", -53, 22)
    f.reload = createStandardButton(f, 90, 20, "Reload UI", "ReloadUI", "RIGHT", f.okay, "LEFT", -5, 0)
    
    -- Profile Dropdown
    local dropdown = CreateFrame("Frame", "OverlordProfileDropDown", f, "UIDropDownMenuTemplate")
    dropdown:SetPoint("TOPLEFT", 21, -17 - stretch)
    self.dropdown = dropdown
    local t = f:CreateFontString(nil,nil,"GameFontNormal") t:SetPoint("BOTTOMLEFT", OverlordProfileDropDownLeft,"TOPRIGHT", 0, -15) t:SetText("Select Profile:")
    
    local list,prev = {}
    for i=1,math.min( 22, numAddOns ) do
        local e = self:CreateAddonEntry(f)
        list[i] = e
        if prev then
            e:SetPoint("TOP",prev,"BOTTOM",0,0)
        else
            e:SetPoint("TOPLEFT", 47, -57 - stretch)
        end
        prev = e
        e:SetAddon(i)
    end    
    self.list = list
    
    -- Hide the scroll bar if there is enough space to display all the user's addons
    if numAddOns <= 22 then
        bar:Hide()
    end
    
    self:ProfileDropDownSetup()
end

function Overlord:OnShow()
    self.frame.bar:SetValue(0)
end

function Overlord:ScrollbarOnValueChanged(bar, value)
    local min,max = bar:GetMinMaxValues()
    bar.upButton:Enable()
    bar.downButton:Enable()
    if value == min then
        bar.upButton:Disable()
    elseif value == max then
        bar.downButton:Disable()
    end
    self:UpdateList(value)
end

function Overlord:ProfileDropDownSetup()
    UIDropDownMenu_SetWidth(150, self.dropdown)
    UIDropDownMenu_JustifyText("LEFT", self.dropdown)
    UIDropDownMenu_Initialize(self.dropdown, function() self:ProfileDropDownInit() end)
end

local profileKeys = {}

local function dropdownOnClick()
    Overlord:ProfileDropDownOnClick()
end

function Overlord:ProfileDropDownInit()
    local profileKeys, n = self.db:GetProfiles(profileKeys)
    
    for i=n+1,#profileKeys do
        profileKeys[i] = nil
    end
    
    table.sort(profileKeys)
    
    local current = self.db.profileKey
    
    local info = UIDropDownMenu_CreateInfo()
    info.text = "Select a profile:"
    info.notClickable = true
    info.isTitle = true
    UIDropDownMenu_AddButton(info)
    
    for i, profile in ipairs(profileKeys) do
        local info = UIDropDownMenu_CreateInfo()
        info.text = profile
        info.value = profile
        info.checked = profile == current
        info.func = dropdownOnClick
        UIDropDownMenu_AddButton(info)
    end
    
    local info = UIDropDownMenu_CreateInfo()
    info.text = "Profile Operations:"
    info.notClickable = true
    info.isTitle = true
    UIDropDownMenu_AddButton(info)
    
    local info = UIDropDownMenu_CreateInfo()
    info.text = "Create A New Profile"
    info.value = -1
    info.func = dropdownOnClick
    UIDropDownMenu_AddButton(info)

    local info = UIDropDownMenu_CreateInfo()
    info.text = "Delete A Profile"
    info.value = -2
    info.func = dropdownOnClick
    UIDropDownMenu_AddButton(info)

    UIDropDownMenu_SetSelectedValue(self.dropdown, current)
end

function Overlord:ProfileDropDownOnClick()
    local value = this.value
    if value == -1 then
        StaticPopup_Show("OVERLORD_NEW_PROFILE")
    elseif value == -2 then
        StaticPopup_Show("OVERLORD_DELETE_PROFILE")
    elseif value ~= self.db.profileKey then
        self.db:SetProfile(value)
        UIDropDownMenu_SetSelectedValue(self.dropdown, value)
    end
end


function Overlord:OnMouseWheel(delta)
    if delta > 0 then
        self.frame.bar:SetValue(self.frame.bar:GetValue() - 7)
    elseif delta < 0 then
        self.frame.bar:SetValue(self.frame.bar:GetValue() + 7)
    end    
end

function Overlord:ShowErrorTooltip(anchorFrame, text)
    if not self.errorTooltip then 
        self.errorTooltip = CreateFrame("GameTooltip","OverlordErrorTooltip",UIParent,"GameTooltipTemplate")
        self.errorTooltip.line1 = OverlordErrorTooltipTextLeft1
    end
    local tooltip  = self.errorTooltip
    tooltip:SetOwner(anchorFrame,"ANCHOR_NONE")
    tooltip.line1:SetWidth(anchorFrame:GetWidth() - 10)
    tooltip:AddLine(text)
    tooltip:Show()
    tooltip:SetPoint("TOPLEFT", anchorFrame, "BOTTOMLEFT")
    tooltip:SetPoint("TOPRIGHT", anchorFrame, "BOTTOMRIGHT")
end

function Overlord:HideErrorTooltip()
    if self.errorTooltip then self.errorTooltip:Hide() end
end

StaticPopupDialogs["OVERLORD_RELOAD_UI"] = {
    text = "Reload your interface?",
    button1 = OKAY,
    button2 = CANCEL,
    
    timeout = 0,
    whiledead = 1,
    showAlert = 1,
    OnAccept = function() ReloadUI() end,
}
StaticPopupDialogs["OVERLORD_NEW_PROFILE"] = {
    text = "Enter the name of the new profile you would like to create",
    whileDead = 1,
    hasEditBox = 1,
    timeout = 0,
    maxletters = 32,
    button1 = ACCEPT,
    button2 = CANCEL,
    showAlert = 1,
    
    OnShow = function()
        local name = this:GetName()
        getglobal(name .. "Button1"):Disable()
        getglobal(name .. "EditBox"):SetFocus()
        getglobal(name .. "AlertIcon"):Hide()
    end,

    OnHide = function()
        Overlord:HideErrorTooltip()
        getglobal(this:GetName() .. "EditBox"):SetText("")
    end,
    
    OnAccept = function(text)
        Overlord.db:SetProfile(text)
        UIDropDownMenu_SetText(text, OverlordProfileDropDown)
    end,
    
    EditBoxOnTextChanged = function()
        local text = this:GetText()
        local dialog = this:GetParent()
        local name = dialog:GetName()
        dialog.data = text
        
        local button1 = getglobal( name .. "Button1" )
        local alertIcon = getglobal( name .. "AlertIcon" )
        
        if Overlord.db.profiles[text] then
            Overlord:ShowErrorTooltip(dialog, "A profile with that name already exists.")
            button1:Disable()
            alertIcon:Show()
        elseif text ~= "" then
            button1:Enable()
            alertIcon:Hide()
            Overlord:HideErrorTooltip()
        elseif text == "" then
            alertIcon:Hide()
            button1:Disable()
            Overlord:HideErrorTooltip()
        end
        
    end,
    
    EditBoxOnEnterPressed = function()
        getglobal(this:GetParent():GetName() .. "Button1"):Click()
    end,
    
    EditBoxOnEscapePressed = function() this:GetParent():Hide() end,
}

StaticPopupDialogs["OVERLORD_DELETE_PROFILE"] = {
    text = "Enter the name of the profile you would like to delete",
    whileDead = 1,
    hasEditBox = 1,
    timeout = 0,
    maxletters = 32,
    button1 = DELETE,
    button2 = CANCEL,
    showAlert = 1,
    
    OnShow = function()
        local name = this:GetName()
        getglobal(name .. "Button1"):Disable()
        getglobal(name .. "EditBox"):SetFocus()
        getglobal(name .. "AlertIcon"):Hide()
    end,

    OnHide = function()
        Overlord:HideErrorTooltip()
        getglobal(this:GetName() .. "EditBox"):SetText("")
    end,
    
    OnAccept = function(text)
        Overlord.db:DeleteProfile(text)
    end,
    
    EditBoxOnTextChanged = function()
        local text = this:GetText()
        local dialog = this:GetParent()
        local name = dialog:GetName()
        dialog.data = text
        
        local button1 = getglobal( name .. "Button1" )
        local alertIcon = getglobal( name .. "AlertIcon" )
        
        if text == "" then
            alertIcon:Hide()
            button1:Disable()
            Overlord:HideErrorTooltip()
        elseif not Overlord.db.profiles[text] then
            Overlord:ShowErrorTooltip(dialog, "No profile by that name exists.")
            button1:Disable()
            alertIcon:Show()
        elseif text == Overlord.db.profileKey then
            Overlord:ShowErrorTooltip(dialog, "You cannot delete your current profile.  Change profiles and try again.")
            button1:Disable()
            alertIcon:Show()
        elseif text ~= "" then
            button1:Enable()
            alertIcon:Hide()
            Overlord:HideErrorTooltip()
        end
        
    end,
    
    EditBoxOnEnterPressed = function()
        getglobal(this:GetParent():GetName() .. "Button1"):Click()
    end,
    
    EditBoxOnEscapePressed = function()this:GetParent():Hide() end,
}